/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package org.xhy.sniffer.datacarrier.buffer;


import org.xhy.sniffer.datacarrier.common.AtomicRangeInteger;

import java.util.List;

/**
 * 自己实现的环形队列。
 */
public class Buffer<T> implements QueueBuffer<T> {
    private final Object[] buffer; // 环形队列的内部存储结构，用一个数组来实现
    private BufferStrategy strategy; // 缓冲区的策略（例如是否覆盖数据等）
    private AtomicRangeInteger index; // 用于管理数组下标的线程安全计数器

    // 构造函数，初始化缓冲区大小和缓冲策略
    Buffer(int bufferSize, BufferStrategy strategy) {
        buffer = new Object[bufferSize]; // 初始化数组作为环形队列的存储空间
        this.strategy = strategy; // 设置缓冲区策略
        index = new AtomicRangeInteger(0, bufferSize); // 初始化下标计数器，范围从 0 到 bufferSize
    }

    // 设置新的缓冲区策略
    @Override
    public void setStrategy(BufferStrategy strategy) {
        this.strategy = strategy;
    }

    /**
     * 保存数据到环形队列中。
     * 如果数组对应位置已有数据，则根据策略决定是否覆盖。
     */
    @Override
    public boolean save(T data) {
        int i = index.getAndIncrement(); // 获取当前的下标并递增
        if (buffer[i] != null) { // 如果当前位置已有数据
            switch (strategy) {
                case IF_POSSIBLE: // 如果策略是不覆盖数据，则返回 false
                    return false;
                default:
                    // 其他策略可以考虑覆盖数据
            }
        }
        buffer[i] = data; // 将新数据存入数组当前位置
        return true; // 返回 true 表示数据成功存储
    }

    // 获取缓冲区的大小
    @Override
    public int getBufferSize() {
        return buffer.length;
    }

    /**
     * 获取缓冲区中的数据并清空已消费的数据。
     * 将缓冲区中所有非空的数据取出并放入 `consumeList`。
     */
    @Override
    public void obtain(List<T> consumeList) {
        this.obtain(consumeList, 0, buffer.length); // 默认取整个缓冲区的数据
    }

    /**
     * 获取指定范围内的数据并清空。
     * 从 `start` 到 `end` 索引之间的数据取出并放入 `consumeList`，取出的数据位置会被清空。
     */
    void obtain(List<T> consumeList, int start, int end) {
        for (int i = start; i < end; i++) { // 遍历指定范围内的缓冲区
            if (buffer[i] != null) { // 如果当前位置有数据
                consumeList.add((T) buffer[i]); // 将数据添加到消费列表
                buffer[i] = null; // 清空该位置的数据
            }
        }
    }
}

